--- Test for 'https://github.com/Frege/frege/issues/65 Issue65'
module tests.comp.Issue65 where

--- Used to go up to 2GB memory and die even when compiled with -O, which yields
--- > println (take 1 (drop 30_000_000 [1..]))
--- Goes up to 2GB memory and dies when not compiled with -O
--- The reason being that the list is passed to a Fun2 for drop, from whence it never escapes.
{--
    There is a bigger problem here.
    Whenever we get yet-to-produce shared data via an argument and pass it on to
    another function (like in the the application of partially applied 'drop' 
    through '•' below), that data stays intact until the outer function returns.
    
    Hence, to avoid memory issues, a "producer" like @[1..]@) must get passed
    directly to a consumer, without passing through intervening functions, no
    matter if those functions are proper frege functions or runtime methods 
    that collect arguments for partial applications.
    
    Another example would be
     
    > sum [1..30_000_000]
      
    When 'sum' is not inlined, it calls
    
    > fold (+) 0 [1..30_000_000]
    
    which is in Java approximately:
    
    > return List.fold(plusfunc, 0, arg1);
    
    and sure enough, 'fold' goes through the list, discarding one front element 
    after the other. But in 'sum', the list is still reachable through the 
    argument, despite it is practically inaccessible, and so nothing gets garbage collected.  
-}
main as = print "Dropping ... " >> (println . take 1 . drop 30_000_000) [1..]
